#include <stdlib.h>
#include <string.h>

#include "netlist.h"
#include "hash.h"

node ** create_hash_table(int size)
{
    node **table;
    table = (node **) calloc(size, sizeof(node*));
    return table;
}

/*
 * Calculate the hash with the help of the djb algorithm given the key and len
 */
unsigned djb_hash (char *key, int len)
{
    char *p = key;
    unsigned h = 0;
    int i;
    for ( i = 0; i < len; i++ )
	h = 33 * h ^ p[i];
    return h;
}


struct circuit_item *get_circuit_item(node *table[], int size, char *key )
{
	/*calulate the index of the given key in the table*/
  int index = djb_hash ( key, strlen ( key ) ) % size;
  node *it = table[index];
  
  /* Find a matching key in the list, if any */
  while ( it != NULL && strcmp ( it->data, key ) != 0 )
      it = it->next;
  
  /*When found return the item else return NULL*/
  if (it)
    return it->net_item;
  else
    return NULL;
}

/*search for a certain item, when found return 1 else return 0*/
int find(node *table[], int size, char *key )
{
  return get_circuit_item (table, size, key ) != NULL;
}

int insert(node *table[], int size, char *key, struct circuit_item *net)
{
  node *it;	 

  /*when not found create new node*/
  if ( !find ( table, size, key ) ) {
    
    /* Find the linked list we want to search */
    unsigned index = djb_hash ( key, strlen ( key ) ) % size;
    node *new_node = malloc ( sizeof *new_node );
    if ( new_node == NULL )
      return 0;
    
    new_node->data = malloc ( strlen ( key ) + 1 );
    new_node->net_item = net;
    new_node->next = NULL;
    
    if ( new_node->data == NULL )
      return 0;
    
    /* Fill in the data and link to the end of current list */
    strcpy ( new_node->data, key );
      
    it = table[index];
    
    /* if the index is empty, store the new node on first position  */
    if (it == NULL)			
    {
      table[index] = new_node;   
      return 1;
    }   
    
    /* get last element of list. */
    while (it->next != NULL)
	it = it->next;
    
    /* append the new node, after the last element */
    it->next = new_node;
        
    return 1;
  }
  return 0;
}

/*loop trough all nodes of the table and free all memory*/
void clean_hash(node *table[], int size){
	int i=0;
	for(i=0; i < size; i++){
		node *tmp = table[i];
		while(tmp){
			free_circuititem(tmp->net_item);
			free(tmp->data);
			node *tmp_next = tmp->next;
			free(tmp);
			tmp = tmp_next;
		}
	}
}
